<template>
  <div
    class="message-point"
    :style="{
      transform: `translateX(${x}px) translateY(${y}px) scale(${
        value === 0 ? 0 : 1
      })`,
      transition: `${transition}s`,
    }"
  >
    <div
      @mousedown="onDown"
      class="message-point-number"
      :style="{
        '--message-point-text-color': textColor,
      }"
    >
      {{ value }}
    </div>
    <svg
      class="change"
      width="200"
      height="200"
      xmlns="http://www.w3.org/2000/svg"
      :style="{
        '--message-point-color': color,
      }"
    >
      <circle
        v-show="!isLeft"
        :cx="100 - x"
        :cy="100 - y"
        :r="stayRound"
        fill="var(--message-point-color)"
      />
      <circle cx="100" cy="100" :r="size" fill="var(--message-point-color)" />
      <line
        v-show="!isLeft"
        x1="100"
        y1="100"
        :x2="100 - x"
        :y2="100 - y"
        stroke="var(--message-point-color)"
        :stroke-width="stayRound"
      />
    </svg>
  </div>
</template>
<script setup lang="ts">
import { computed, ref } from "vue";
import { watchCount, setCount, getCount } from "@/hooks/useCounter";
const emit = defineEmits(["clear"]);
const stayRound = computed(() =>
  Math.max(0, (Math.min(1, 1 - distance.value / 80) * props.size * 2) / 3)
);
const isLeft = ref(false);
const props = withDefaults(
  defineProps<{
    size?: number;
    draggable?: boolean;
    clearable?: boolean;
    bindCounter?: string;
    color?: Color;
    textColor?: Color;
  }>(),
  {
    size: 15,
    draggable: false,
    clearable: false,
  }
);
if (props.size < 10) {
  console.warn(
    "The size of MessagePoint is to small to show, it required to more than 10."
  );
}
const transition = ref(0);
const isDown = ref(false);
const value = ref(0);
if (props.bindCounter) {
  const v = getCount(props.bindCounter as string);
  if (v) value.value = v;
  watchCount(props.bindCounter, (v) => {
    transition.value = 0.3;
    value.value = v;
    setTimeout(() => {
      transition.value = 0;
    }, 100);
  });
}
const x = ref(0);
const y = ref(0);
const distance = computed(() =>
  Math.sqrt(Math.pow(x.value, 2) + Math.pow(y.value, 2))
);
const onDown = () => {
  isDown.value = true;
  isLeft.value = false;
};
document.addEventListener("mouseup", () => {
  if (isDown.value) {
    if (distance.value > 60 && props.clearable) {
      if (props.bindCounter) {
        setCount(props.bindCounter, 0);
      } else {
        value.value = 0;
      }
      emit("clear");
    } else {
      x.value = y.value = 0;
    }
    transition.value = 0.3;
    isDown.value = false;
    setTimeout(() => {
      x.value = y.value = 0;
      transition.value = 0;
    }, 300);
  }
});
document.addEventListener("mousemove", (e: MouseEvent) => {
  if (isDown.value && props.draggable) {
    if (distance.value > 60) {
      if (!isLeft.value) {
        isLeft.value = true;
      }
    }
    const maxLeave = 50;
    let nx = x.value + e.movementX;
    let ny = y.value + e.movementY;
    if (props.clearable) {
      x.value = nx;
      y.value = ny;
    } else {
      //不可清除时，拽不断
      if (nx > 0) {
        x.value = Math.min(
          nx,
          Math.sqrt(Math.pow(maxLeave, 2) - Math.pow(y.value, 2))
        );
      } else {
        x.value = Math.max(
          nx,
          -Math.sqrt(Math.pow(maxLeave, 2) - Math.pow(y.value, 2))
        );
      }
      if (ny > 0) {
        y.value = Math.min(
          ny,
          Math.sqrt(Math.pow(maxLeave, 2) - Math.pow(x.value, 2))
        );
      } else {
        y.value = Math.max(
          ny,
          -Math.sqrt(Math.pow(maxLeave, 2) - Math.pow(x.value, 2))
        );
      }
    }
  }
});
</script>
<style lang="less">
.message-point {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  position: relative;

  .message-point-number {
    z-index: 100;
    cursor: pointer;
    user-select: none;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    color: var(--message-point-text-color);
    padding: 1px;
    width: 30px;
    height: 30px;
    line-height: 13px;
    font-size: 13px;
    transform-origin: center;
    scale: 1;
    position: absolute;
    border-radius: 100%;
  }

  .change {
    z-index: -1;
    position: absolute;
  }
}

.message-point.zero {
  scale: 0;
  transition: 0.3s;
}
</style>
